/**
 * Escalonamento
 * --------------------------------------
 *
 * Quando eh necessario escalonar:
 *      - Quando cria um novo processo 
 *      - Quando termina um processo (removido) 
 *      - Quando ocorre uma interrupcao 
 *      - Quando eh bloqueado por I/O, semafaro ou outra situacao. 
 *
 * @author Caio Thomas Oliveira 11011BSI209
 * @author Leonardo Pimentel Ferreira	11011BSI223
 */

#ifndef ESCALONAMENTO_H
#define	ESCALONAMENTO_H


#ifdef	__cplusplus
extern "C" {
#endif        
   
    /**
     * Obtêm um quantum randômico que será recebido por um processo.
     */
    int esc_get_quantum();	

    /**
     * Realiza o algoritmo de escalonamento por loteria na estrutura de processos prontos.
     */
    void escalonarLoteria();

    /**
     * Escolhe para ser executado um dos algoritmos de escalonamento.
     */
    void esc_escolhe_algoritmo_escalonamento();

    /**
     * Realiza o algoritmo de escalonamento circular (Round-robin) na estrutura de processos prontos.
     */
    void escalonarCircular();

    /**
     * Essa função altera o processo estado do processo em execução para pronto e coloca um novo processo em execução.
     */
    void esc_escalona();

    /**
     * Imprime um processo que foi finalizado ou ocorreu erro fatal.
     */
    void esc_processo_finalizado();

    /**
     * Função que salva na tabela de processo o estado e dados do processo em execução e remove o primeiro processo da estrutura de processos prontos e altera o estado deste para executando.
     */
    void esc_get_primeiro_fila_pronto_to_exe();

    /**
     * Função que salva na tabela de processo o estado e dados do processo em execução e insere-o na estrutura de processos prontos.
     */
    void esc_exe_to_pronto();

    /**
     * Função que executa as entradas e saídas dos processos bloqueados por entradas e saídas. Além disso, verifica se a entrada e saída já foi finalizada e caso seja positivo insere o processo na estrutura de processos prontos.
     */
    void esc_verifica_bloqueio();

    /**
     * Esta função é chamada depois que algum processo novo foi instanciado. Ela é responsável por inserir um processo na estrutura de processos prontos, ou em execução (quando a CPU está ociosa e não tem processo na estrutura de processos prontos). Se o processo foi inserido na estrutura de processos prontos um algoritmo de escalonamento é realizado.
     * @param processo que acaba de ser instanciado.
     */
    void esc_executa_processo(Processo* processo);

    /**
     * Essa função simula a criação e inserção de novos processos de tempos em tempos durante a execução do sistema. 
     */
    void esc_tempo_novo_processo();

    /**
     * Nesta função recursiva onde o ponto de parada é quando não tem mais processos para serem executados está a lógica de execução dos processos e de suas transições de estados.
     */
    void esc_executa();

    /**
     * Salva o estado e dados do processo em execução em sua respectiva tabela de processo para realizar escalonamento.
     * @param proximo_estado_do_processo_execucao. Próximo estado do processo em execução (BLOQUEADO ou PRONTO).
     */
    void salvaEstadoProcessoExecucao(int proximo_estado_do_processo_execucao);

    /**
     * Essa função finaliza e imprime o tempo de execução de um processo.
     */
    void fim_processo();
    
    void verifica_processo_encerrou_estava_regiao_critica();
    

#ifdef	__cplusplus
}
#endif

#endif	/* ESCALONAMENTO_H */

